package com.scenic.scenicservice.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.scenic.common.bean.Addr;
import com.scenic.common.bean.Category;
import com.scenic.common.bean.ScenicSpot;
import com.scenic.common.exception.ScenicSpotException;
import com.scenic.common.service.AddrService;
import com.scenic.common.service.ScenicSpotService;
import com.scenic.scenicservice.mapper.CategoryMapper;
import com.scenic.scenicservice.mapper.ScenicSpotMapper;
import com.scenic.scenicservice.mapper.ScenicSpotPicMapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

import static com.scenic.common.utils.RedisConstants.GOODS_CACHE;

@DubboService
public class ScenicSpotServiceImpl implements ScenicSpotService {
    @Autowired
    private ScenicSpotMapper scenicMapper;
    @Autowired
    private ScenicSpotPicMapper scenicSpotPicMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @DubboReference
    private AddrService addrService;
    /**
        *1. 所属分类是否存在，并且必须是子分类
        * 2. 不能添加同名景区
            * 姓名
            * 分类
            * 地址 
        3. 添加景区
        4. 添加景区图片
        * */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insert(ScenicSpot scenicSpot) throws ScenicSpotException {
        //所属分类是否存在，必须是子分类
        Category category = categoryMapper.selectById(scenicSpot.getCategoryId());
        if (category == null || (category != null && category.getParentId().equals(0))){
            throw new ScenicSpotException("所属分类不存在或者分类是父分类无法添加");
        }
        System.out.println(scenicSpot.getAddr());
        /*
        * 添加地址
        * 如果地址不存在则添加
        * 如果地址存在则用之前的地址
        * */
        List<Addr> addrs = addrService.selectByCondition(scenicSpot.getAddr());
        if (!addrs.isEmpty()) {
            scenicSpot.setAddrId(addrs.get(0).getId());
        }else{
            scenicSpot.setAddrId(addrService.insert(scenicSpot.getAddr()));
        }
        /*
         * 2. 不能添加同名景区
         * 姓名
         * 分类
         * 地址
         * */
        ScenicSpot condition = new ScenicSpot();
        scenicSpot.setCategoryId(scenicSpot.getCategoryId());
        scenicSpot.setAddr(scenicSpot.getAddr());
        scenicSpot.setName(scenicSpot.getName());

        if (scenicMapper.selectByCondition(condition)
                .stream()
                .anyMatch(item -> item.getName().equals(scenicSpot.getName()))) {
            throw new ScenicSpotException("存在相同景区，无法添加");
        }

        //添加景区
        scenicMapper.insert(scenicSpot);
        //判断是否图片需要添加
        if (scenicSpot.getPicList()!= null && scenicSpot.getPicList().size() > 0) {
            //添加图片的景区id
            scenicSpot.getPicList()
                    .stream()
                    .forEach(pic -> pic.setScenicSpotId(scenicSpot.getId()));
            scenicSpotPicMapper.insert(scenicSpot.getPicList());
        }
    }
    /**
     * 判断景点是否存在
     * 判断景点关联订单
     * 删除景点图片
     * 删除景点
     * */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long id) throws ScenicSpotException {
        //判断景区是否存在
        if (scenicMapper.selectById(id) == null) {
            throw new ScenicSpotException("景区不存在，无法删除");
        }
        //todo 判断是否关联订单
        //删除景区图片
        scenicSpotPicMapper.delete(id);
        //删除景区
        scenicMapper.delete(id);

    }

    /**
     * 判断景点是否存在
     * 判断修改之后的分类是否存在 —— 前提是必须修改分类
     * 不能同名
     * 修改景点信息
     * 修改图片
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(ScenicSpot scenicSpot) throws ScenicSpotException {
        ScenicSpot newInfo = scenicSpot;
        ScenicSpot oldInfo = scenicMapper.selectById(scenicSpot.getId());
        //判断景区是否存在
        if (oldInfo == null) {
            throw new ScenicSpotException("景区不存在，无法修改");
        }
        //判断是否修改了分类
        if (newInfo.getCategoryId() != null && !newInfo.getCategoryId().equals(oldInfo.getCategoryId())){
            //判断修改之后的分类是否存在并且必须是子分类
            Category category = categoryMapper.selectById(newInfo.getCategoryId());
            if (category == null ||(category != null && category.getParentId().equals(0))) {
                throw new ScenicSpotException("修改之后的分类不存在或者修改之后的分类是父分类无法修改");
            }
        }
        /*
         * 2. 不能同名景区
         * 姓名
         * 分类
         * 地址
         * */
        Integer newCategoryId = newInfo.getCategoryId() == null ? oldInfo.getCategoryId() : newInfo.getCategoryId();
        String newName = newInfo.getName() == null ? oldInfo.getName() : newInfo.getName();
        Integer newAddrId = newInfo.getAddrId() == null ? oldInfo.getAddrId() : newInfo.getAddrId();
        ScenicSpot condition = new ScenicSpot();
        condition.setCategoryId(newCategoryId);
        condition.setName(newName);
        condition.setAddrId(newAddrId);

        if (scenicMapper.selectByCondition(condition)
                .stream()
                .anyMatch(item -> item.getName().equals(newName) && !item.getId().equals(newInfo.getId()))) {
            throw new ScenicSpotException("存在相同景区，无法修改");
        }

        //修改景区信息
        scenicMapper.update(scenicSpot);
        String key = GOODS_CACHE+ scenicSpot.getId();
        stringRedisTemplate.delete(key);
        /*
         * 修改图片
         * 1. 删除之前的图片
         * 2. 添加
         * */
        if (newInfo.getPicList() != null && newInfo.getPicList().size() > 0){
            scenicSpotPicMapper.delete(newInfo.getId());
            newInfo.getPicList()
                    .stream()
                    .forEach(item -> item.setScenicSpotId(newInfo.getId()));
            //添加图片
            scenicSpotPicMapper.insert(newInfo.getPicList());
        }
    }

    @Override
    public ScenicSpot selectById(Long id) throws ScenicSpotException {
        ////设置查询的key
        //String key = GOODS_CACHE + id;
        ////从redis查询景区缓存
        //String scenicSpotJson = stringRedisTemplate.opsForValue().get(key);
        ////判断是否存在
        //if (!StrUtil.isBlank(scenicSpotJson)) {
        //    //存在，直接返回
        //    ScenicSpot scenicSpot = JSONUtil.toBean(scenicSpotJson, ScenicSpot.class);
        //    return scenicSpot;
        //}
        //if (scenicSpotJson != null) {
        //    throw new ScenicSpotException("景区不存在");
        //}
        ScenicSpot scenicSpot = scenicMapper.selectById(id);

        if (scenicSpot == null) {
            //设置缓存空值
            //stringRedisTemplate.opsForValue().set(key, "", 2L, TimeUnit.MINUTES);
            throw new ScenicSpotException("景区不存在");
        }else {
            scenicSpot.setAddr(addrService.selectById(scenicSpot.getAddrId()));
        }
        //stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(scenicSpot),30L, TimeUnit.MINUTES);
        return scenicSpot;
    }


    @Override
    public PageInfo<ScenicSpot> selectByCondition(ScenicSpot condition, Integer pageNum, Integer pageSize) {
        //设置分页参数
        PageHelper.startPage(pageNum, pageSize);
        //查询
        List<ScenicSpot> scenicSpot = scenicMapper.selectByCondition(condition);
        for (ScenicSpot spot : scenicSpot) {
            if( spot.getAddrId() != null){
                spot.setAddr(addrService.selectById(spot.getAddrId()));
            }
        }
        PageInfo<ScenicSpot> pageInfo = new PageInfo<>(scenicSpot);
        return pageInfo;
    }

    @Override
    public PageInfo<ScenicSpot> selectByCondition1(ScenicSpot condition, Integer pageNum, Integer pageSize) {
        //设置分页参数
        PageHelper.startPage(pageNum, pageSize);
        //查询
        List<ScenicSpot> scenicSpot = scenicMapper.selectByCondition(condition);
        PageInfo<ScenicSpot> pageInfo = new PageInfo<>(scenicSpot);
        return pageInfo;
    }

    @Override
    public List<Map<String, Object>> scenicSpotSaleTop5() {

        //List<Map<String, Object>> list = scenicMapper.scenicSpotSaleTop5();
        //todo 显示景区销量前5
        return null;
    }
}
